package fr.inria.phoenix.scenario.bwsnfirefighting.framework.distributed.buildingalertdetection;

import java.util.HashMap;

import fr.inria.diagen.core.ServiceConfiguration;
import fr.inria.diagen.core.exception.DiaGenException;
import fr.inria.diagen.core.exception.InvocationException;
import fr.inria.diagen.core.network.RemoteServiceInfo;
import fr.inria.diagen.core.service.local.Service;

import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel;
import java.lang.Boolean;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location;

import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.AlertDetectionDataType;
import fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.AlertDetectionIndices;
import fr.inria.diagen.core.service.proxy.Proxy;
import fr.inria.diagen.core.module.event.IEventNotifyListener;
import fr.inria.diagen.core.module.command.ICommandListener;
import fr.inria.diagen.core.server.local.EventSubscription;
import fr.inria.diagen.core.service.filter.service.ServiceFilter;
import fr.inria.diagen.core.exception.InvocationException;

/**
 * **************
 *  * CONTEXTS
 *  **************
 *
 * @[73,1]
 * context BuildingAlertDetection as DangerLevel {
 * source activated from ManualButton;
 * context AlertDetection;
 * }
 */
public abstract class BuildingAlertDetection extends Service implements IEventNotifyListener, ICommandListener {
  /**
     * @param serviceConfiguration
     */
    public BuildingAlertDetection(ServiceConfiguration serviceConfiguration ) {
      super("BuildingAlertDetection", serviceConfiguration, GeneratedFramework.getInstance());
    }

	protected final void _postInitialize() {
			subscribeAlertDetection();
		
		postInitialize();
	}
	protected void postInitialize() {}


    private fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel buildingAlertDetection;
    /**
     * @[73,1]
     * context BuildingAlertDetection as DangerLevel {
     * source activated from ManualButton;
     * context AlertDetection;
     * }
     */  
    protected void setBuildingAlertDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel newBuildingAlertDetectionValue ) {
      buildingAlertDetection = newBuildingAlertDetectionValue;
      getServer().publish("BuildingAlertDetection", newBuildingAlertDetectionValue); 
    }

    /**
     * @[73,1]
     * context BuildingAlertDetection as DangerLevel {
     * source activated from ManualButton;
     * context AlertDetection;
     * }
     */
    protected fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel getBuildingAlertDetection() {
      return buildingAlertDetection;    }
    
    public final Object commandReceived(RemoteServiceInfo rsi, String methodName, Object... args) throws DiaGenException {
      if (methodName.equals("getBuildingAlertDetection"))
        return (fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel) getBuildingAlertDetection();

      throw new InvocationException("Unsupported method call: " + methodName);
    }
    
    public void notifyReceived(RemoteServiceInfo servicePublisher, String eventName, Object arg) {
        try {
          if (eventName.equals("activated") && servicePublisher.getClassName().equals("ManualButton")) {
            onNewActivated ((ManualButtonProxy) createProxy(servicePublisher),(java.lang.Boolean) arg);          }
 else          if (eventName.equals("AlertDetection") && servicePublisher.getClassName().equals("AlertDetection")) {
            AlertDetectionDataType data = (AlertDetectionDataType) arg;
            onNewAlertDetection ((fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel) data._dataSourceValue_, data.indices.location);          }

        } catch (Exception e) {
              e.printStackTrace();
        }
    }

    public abstract void onNewActivated(ManualButtonProxy proxy,java.lang.Boolean newActivatedValue);
    
    public void subscribeActivated(ManualButtonProxy proxy) {
      getServer().subscribe(new EventSubscription(proxy.getRemoteServiceInfo(), getServiceInfo(), "activated"), 3600);
    }    public abstract void onNewAlertDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel newAlertDetectionValue, fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location);
    
    
    private final void subscribeAlertDetection() {
      getServer().subscribe(new EventSubscription(getAlertDetectionRSI(), getServiceInfo(), "AlertDetection"), 3600);
    }

    private RemoteServiceInfo getAlertDetectionRSI() {
      ServiceFilter filter = new ServiceFilter("AlertDetection");
      RemoteServiceInfo[] rsis = getServicesInfo(getServer(), filter);
      return rsis[0];
    }
    
    protected final fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel getAlertDetection(fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.Location location) throws InvocationException {
      return (fr.inria.phoenix.scenario.bwsnfirefighting.framework.datatype.DangerLevel) getProcessor().command(getAlertDetectionRSI(), "getAlertDetection", location);
    }
    

    protected final ManualButtonComposite discover(ManualButtonServiceFilter filter) {
      RemoteServiceInfo[] rsis = getServicesInfo(getServer(), filter);
      ManualButtonProxy[] proxies = new ManualButtonProxy[rsis.length];
      for (int i = 0; i < rsis.length; i++) {
        proxies[i] = new ManualButtonProxy(getProcessor(), rsis[i]);
      }
      return new ManualButtonComposite(proxies, this);
    }
    
    protected final ManualButtonComposite allManualButtons() {
        return discover(new ManualButtonServiceFilter());
    }
    
    protected final ManualButtonServiceFilter manualButtonsWhere() {
        return new ManualButtonServiceFilter();
    }

}